using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;

namespace Mysoft.Dbf.Writers
{
    public class ContentWriter : IWriter
    {
        PropertyInfo_WriterPair[] _fields;
 
        public ContentWriter(Type contentType)
        {
            LoadFields(contentType);
        }

        private void LoadFields(Type contentType)
        {
            List<PropertyInfo_WriterPair> rez = new List<PropertyInfo_WriterPair>();
            foreach (PropertyInfo prop in contentType.GetProperties())
            {
                ExportToDBFAttributeBase attr = (ExportToDBFAttributeBase)ExportToDBFAttributeBase.GetCustomAttribute(prop, typeof(ExportToDBFAttributeBase));
                if (attr == null)
                    continue;
                rez.Add(new PropertyInfo_WriterPair(prop, attr.GetWriter()));
            }
            _fields= rez.ToArray();
        }

        #region IFieldWriter Members

        public void WriteHeader(Stream toStream, int offsetInRecord, NamingParameters namingParameters)
        {
            int currentOffset = offsetInRecord;
            foreach (PropertyInfo_WriterPair field in _fields)
            {
                field.Writer.WriteHeader(toStream, currentOffset,namingParameters);
                currentOffset += field.Writer.FieldTotalLength;
            }
        }

        public void WriteValue(object row, StreamWriter streamWriter)
        {
            foreach (PropertyInfo_WriterPair field in this._fields)
            {
                if (row == null)
                    field.Writer.WriteValue(null, streamWriter);
                else
                    field.Writer.WriteValue(
                        field.TargetPropertyInfo.GetValue(row, new object[0]) ,
                        streamWriter
                        );
            }
        }

        public short FieldTotalLength
        {
            get
            {
                short rez = 0;
                foreach (PropertyInfo_WriterPair field in this._fields)
                {
                    rez += field.Writer.FieldTotalLength;
                }
                return rez;
            }
        }

        public byte FieldCount
        {
            get
            {
                byte rez = 0;
                foreach (PropertyInfo_WriterPair propertyWriter in this._fields)
                {
                    rez += propertyWriter.Writer.FieldCount;
                }
                return rez;
            }
        }

        #endregion

        private class PropertyInfo_WriterPair
        {
            IWriter _writer;
            PropertyInfo _targetPropertyInfo;
            
            public PropertyInfo_WriterPair(PropertyInfo propertyInfo, IWriter writer)
            {
                _targetPropertyInfo = propertyInfo;
                _writer = writer;
            }

            public PropertyInfo TargetPropertyInfo
            {
                get { return _targetPropertyInfo; }
            }

            public IWriter Writer
            {
                get { return _writer; }
            }
        }
    }
}
